package com.gitee.chili.leisure.service;

import com.gitee.chili.leisure.Callback;
import com.gitee.chili.leisure.ResponseCode;
import com.gitee.chili.leisure.ResponseResult;
import com.gitee.chili.leisure.constant.Constant;
import com.gitee.chili.leisure.domain.dto.RequestModel;
import com.gitee.chili.leisure.properties.NettyHandlerProperties;
import com.gitee.chili.leisure.util.Utils;
import feign.Feign;
import feign.Target;
import feign.codec.Decoder;
import feign.codec.Encoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Service;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Objects;
import java.util.function.Supplier;

/**
 * TerminalService
 *
 * @author week solider
 * @version v1.0
 * @since 01.04.2020
 */

@Slf4j
@Service
@Import(FeignClientsConfiguration.class)
public class GameHandleService implements IGameHandleService {

    private final NettyHandlerProperties properties;

    private final GameTaskTransferClient gameTaskTransferClient;

    @Autowired
    public GameHandleService(Decoder decoder, Encoder encoder, NettyHandlerProperties properties) {
        gameTaskTransferClient = Feign.builder()
                .encoder(encoder)
                .decoder(decoder)
                .target(Target.EmptyTarget.create(GameTaskTransferClient.class));
        this.properties = properties;
    }

    /**
     * 请求执行后的回调，可在此处实现熔断等处理
     *
     * @param supplier 请求参数
     * @param callback 回调函数
     */
    @Override
    public <T> void request(Supplier<RequestModel> supplier, Callback<ResponseResult<T>> callback) {
        try {
            ResponseResult<T> result = handler(supplier.get());
            if (Objects.nonNull(result) && result.getCode().equals(ResponseCode.SUCCESS.getCode())) {
                if (Objects.nonNull(callback)) {
                    log.debug("执行请求回调函数： [ on success execute]");
                    callback.onSuccess(result);
                }
            }
            log.warn("{} 请求失败", supplier.get().getUrl());
        } catch (Exception e) {
            log.error("请求游戏服务异常, errMsg: {}", e.getMessage(), e);
        }
    }

    @SuppressWarnings("unchecked")
    private <T> ResponseResult<T> handler(RequestModel model) throws URISyntaxException {
        log.debug("request url：{} , param: {}", model.getUrl(), model.getData().toString());

        // 解析路径
        String url = parsePath(properties.getGatewayUrl(), model.getUrl());
        return gameTaskTransferClient.handler(new URI(url), model.getData());
    }


    /**
     * 解析 URL 参数中是否存在 "/" 重复的情况，如果是单个路径重复这里不予解决，因为是由于调用者的错误编写方式导致
     *
     * @param preUrl  前置路径
     * @param nextUrl 后置路径
     * @return 需要请求的路径
     */
    private String parsePath(String preUrl, String nextUrl) {

        boolean haveTail = preUrl.endsWith("/");
        boolean haveHead = nextUrl.startsWith("/");

        if (haveTail && haveHead) {
            return Utils.connect(preUrl, nextUrl.substring(1));
        } else if (!haveTail && !haveHead) {
            return Utils.concat(Constant.rootPath, preUrl, nextUrl);
        } else {
            return Utils.connect(preUrl, nextUrl);
        }

    }
}
